//
//  main.cpp
//  
//
//  Created by Kun Zhao on 12/06/12.
//  Copyright (c) 2012 Kyoto University. All rights reserved.
//

#include <iostream>
#include <cstdio>
#include <kvs/PointObject>
#include <kvs/PointImporter>
#include <kvs/PointExporter>
#include <kvs/UnstructuredVolumeObject>
#include <kvs/UnstructuredVolumeImporter>
#include <kvs/CommandLine>
#include <kvs/KVSMLObjectPoint>
#include <kvs/Timer>
#include <kvs/TransferFunction>
#include <kvs/BitArray>
#include <kvs/CommandLine>
#include "TimeVaryingCellByCellSampling.h"

kvs::BitArray* CTImporter( std::string filename, long long CT_length )
{
    kvs::BitArray* CTbit = new kvs::BitArray( CT_length );
    FILE* fp;
    fp = fopen( filename.c_str(), "rb" );
    fread( CTbit->pointer(), 1, CTbit->byteSize(), fp );
    fclose( fp );
    return( CTbit ); 
}

void WriteParticles( kvs::PointObject* point, std::string filename )
{
    kvs::KVSMLObjectPoint* output = new kvs::PointExporter<kvs::KVSMLObjectPoint>( point );
    output->setWritingDataType( kvs::KVSMLObjectPoint::ExternalBinary );
    output->write( filename );
    std::cout << "finish writing: " << filename << std::endl;
    delete output;
}

std::string CreateString( std::string filename, int step, std::string extension )
{
    char buf[10];
    sprintf( buf, "%03d", step );
    return( filename + std::string( buf ) + extension );
}

int main( int argc, char** argv )
{

    size_t step = 3;
    size_t subpixel = 12;
    float samplingstep = 0.001;
    
    std::string filename = "../FS85000/FS85000_";
    std::string outputname= "FS85000CT_";
    std::string PTname = "PT.bin";
    std::vector<PTtype> PT;
    
    kvs::UnstructuredVolumeObject* object[step];
    kvs::TransferFunction tfunc(256);
    kvs::TimeVaryingCellByCellSampling* sampler_current = new kvs::TimeVaryingCellByCellSampling();
    kvs::PointObject* point_current;

    object[0] = new kvs::UnstructuredVolumeImporter( CreateString( filename, 0, ".kvsml" ) );
    unsigned int NumberOfCells = object[0]->ncells();

    // load CT
    long long CT_length = NumberOfCells * ( step - 1 );
    kvs::BitArray* CTbit = CTImporter( "CTbit.bin", CT_length );
    long long loc = 0;
    
    // generate particles for the first step
    kvs::Timer time1;
    time1.start();
    
    sampler_current = new kvs::TimeVaryingCellByCellSampling();
    sampler_current->setSubpixelLevel( subpixel );
    sampler_current->setSamplingStep( samplingstep );
    sampler_current->setTransferFunction( tfunc );
    sampler_current->setCellsTable( CTbit, loc );
    sampler_current->setParticlesTable( &PT );
    sampler_current->isFirstStep();
    point_current = sampler_current->exec( object[0] );
    time1.stop();
    std::cout << "first step time:" << time1.msec() << std::endl;
    WriteParticles( point_current, CreateString( outputname, 0, ".kvsml" ) );
    delete object[0];
    
    // generate particles for the following step
    for ( size_t i = 1; i < step; i++ )
    {
        object[i] = new kvs::UnstructuredVolumeImporter( CreateString( filename, i, ".kvsml" ) );
        
        kvs::Timer time2;
        time2.start();

        sampler_current->setSubpixelLevel( subpixel );
        sampler_current->setSamplingStep( samplingstep );
        sampler_current->setTransferFunction( tfunc );
        sampler_current->setCellsTable( CTbit, loc );
        sampler_current->setParticlesTable( &PT );
        sampler_current->notFirstStep();
        point_current = sampler_current->exec( object[i] ); 
        time2.stop();
        std::cout << "current time:" << time2.msec() << std::endl;
        
        WriteParticles( point_current, CreateString( outputname, i, ".kvsml" ) );
        delete object[i];
        loc += NumberOfCells;
//        delete CT[i];
    }
    
    char* PT_buf = new char[PT.size() + 4];
    memcpy( PT_buf, &NumberOfCells, 4 );
    memcpy( PT_buf + 4, PT.data(), PT.size() );
    
    FILE* fp;
    fp = fopen( PTname.c_str(), "wb" );
    fwrite( PT_buf, 1, PT.size() + 4, fp );    
}